/* 
    在函数式编程当中有一个很重要的概念就是函数组合， 实际上就是把处理数据的函数像管道一样连接起来， 然后让数据穿过管道得到最终的结果。 例如：
    const add1 = (x) => x + 1;
    const mul3 = (x) => x * 3;
    const div2 = (x) => x / 2;
    div2(mul3(add1(add1(0)))); //=>3
​
    而这样的写法可读性明显太差了，我们可以构建一个compose函数，它接受任意多个函数作为参数（这些函数都只接受一个参数），然后compose返回的也是一个函数，达到以下的效果：
    const operate = compose(div2, mul3, add1, add1)
    operate(0) //=>相当于div2(mul3(add1(add1(0)))) 
    operate(2) //=>相当于div2(mul3(add1(add1(2))))

    简而言之：compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x)，请你完成 compose函数的编写 
*/
const add1 = x => x + 1;
const mul3 = x => x * 3;
const div2 = x => x / 2;

/* 
// 完整版
const compose = function compose(...params) {
    let len = params.length;
    if (len === 0) return x => x;
    if (len === 1) return params[0];
    return function operate(x) {
        return params.reduceRight((result, item) => {
            return item(result);
        }, x);
    };
};
console.log(compose(div2, mul3, add1, add1)(0)); //3
console.log(compose(div2, mul3)(3)); //4.5
console.log(compose(div2)(10)); //5
console.log(compose()(10)); //10 
*/

/* 
// 简易版
const compose = function compose(...params) {
    // params：数组，存储了需要执行的函数及其顺序 -> [div2, mul3, add1, add1]
    return function operate(x) {
        // x：第一个函数执行传递的实参 -> 0
        return params.reduceRight((result, item) => {
            // 第一轮：result=0 item=add1 -> add1(0)/1
            // 第二轮：result=1 item=add1 -> add1(1)/2
            // 第三轮：result=2 item=mul3 -> mul3(2)/6
            // 第四轮：result=6 item=div2 -> div2(6)/3
            return item(result);
        }, x);
    };
};
console.log(compose(div2, mul3, add1, add1)(0)); //3 
*/

/* 
let arr = [10, 20, 30, 40];
let res = arr.reduce((result, item, index) => {
    // 第一轮：result=10 item=20 index=1 -> 30「相当于从数组的第二项开始迭代」
    // 第二轮：result=30 item=30 index=2 -> 60
    // 第三轮：result=60 item=40 index=3 -> 100
    return result + item;
});
console.log(res); //100

let res = arr.reduce((result, item, index) => {
    // 第一轮：result=0 item=10 index=0 -> 10「相当于从数组的第一项开始迭代」
    // 第二轮：result=10 item=20 index=1 -> 30
    // ...
    return result + item;
}, 0);
console.log(res); //100 
*/

//===================
/* 
// 课后扩展：分析这段代码是如何处理的
const compose = function compose(...funcs) {
    if (funcs.length === 0) return (arg) => arg;
    if (funcs.length === 1) return funcs[0];
    return funcs.reduce((a, b) => {
        return (x) => {
            return a(b(x));
        };
    });
};
console.log(compose(div2, mul3, add1, add1)(0)); //3
console.log(compose(div2, mul3)(3)); //4.5
console.log(compose(div2)(10)); //5
console.log(compose()(10)); //10  
*/